package org.darkbits.cyklon.util;

public class SimpleOscillators {
	
	public enum Type {
		PULSE,
		SINE,
		SAWTOOTH,
		TRIANGLE
	}
	
	public enum Polarity {
		BIPOLAR,
		UNIPOLAR
	}
	
	public static float bipolarPulse(float phase, float pw) {
		return (phase - Math.floor(phase)) < pw ? 1.0f : -1.0f;
	}
	
	public static float bipolarPulse(float phase) {
		return (phase - Math.floor(phase)) < 0.5 ? 1.0f : -1.0f;
	}
	
	public static float bipolarSine(float phase) {
		return (float)Math.sin(phase * 2 * Math.PI);
	}
	
	public static float bipolarSawtooth(float phase) {
		return (phase - (float)Math.floor(phase)) * 2.0f - 1.0f;
	}
	
	public static float bipolarTriangle(float phase) {
		phase += 0.25f;
		phase = (phase - (float)Math.floor(phase));
		return phase < 0.5f ? phase * 4.0f - 1.0f : 1.0f - phase * 4.0f; 
	}
	
	public static float unipolarPulse(float phase, float pw) {
		return (phase - Math.floor(phase)) < pw ? 1.0f : 0.0f;
	}
	
	public static float unipolarPulse(float phase) {
		return (phase - Math.floor(phase)) < 0.5 ? 1.0f : 0.0f;
	}
	
	public static float unipolarSine(float phase) {
		return (float)Math.sin(phase * 2 * Math.PI) * 0.5f + 0.5f;
	}
	
	public static float unipolarSawtooth(float phase) {
		return (phase - (float)Math.floor(phase));
	}
	
	public static float unipolarTriangle(float phase) {
		phase += 0.25f;
		phase = (phase - (float)Math.floor(phase));
		return phase < 0.5f ? phase * 2.0f : 1.0f - phase * 2.0f; 
	}
	
	public static float oscillator(float phase, Type type, Polarity polarity) {		
		switch(polarity) {
		case BIPOLAR:
			switch(type) {
			case PULSE:
				return bipolarPulse(phase);
			case SINE:
				return bipolarSine(phase);
			case SAWTOOTH:
				return bipolarSawtooth(phase);
			case TRIANGLE:
				return bipolarTriangle(phase);
			}
		case UNIPOLAR:
			switch(type) {
			case PULSE:
				return unipolarPulse(phase);
			case SINE:
				return unipolarSine(phase);
			case SAWTOOTH:
				return unipolarSawtooth(phase);
			case TRIANGLE:
				return unipolarTriangle(phase);
			}
		}
		
		return 0.0f; // Should never happen
	}
}
